﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sinacor.Infra.Service.Data;
using PSE.ProcessManager.Common.Process;

namespace Sinacor.Infra.Core.ProcessManager.Server
{
    public abstract class BaseProcessLogic
    {
        //protected const int _sinacorErrorMessageId = 508;
        private int _companyId = -1;

        public BaseProcessLogic()
        {
            this.Status = new ProcessStatus();
        }

        #region Transactions
        /// <summary>
        /// Inicializa o modo transacional de acesso ao banco de dados
        /// </summary>
        /// <param name="companyId">Identificador da empresa</param>
        protected void BeginTransaction(int companyId)
        {
            _companyId = companyId;
            TransactionCollection.GetInstance().CreateConnectionTransaction(System.Threading.Thread.CurrentThread.ManagedThreadId, companyId);
        }

        /// <summary>
        /// "Entrega" as alterações, inclusões ou deleções feitas no banco de dados
        /// </summary>
        protected void CommitTransaction()
        {
            if (_companyId >= 0)
                TransactionCollection.GetInstance().CommitTransaction(System.Threading.Thread.CurrentThread.ManagedThreadId, _companyId);
        }

        /// <summary>
        /// Descarta as alterações, inclusões ou deleções feitas no banco de dados
        /// </summary>
        protected void RollbackTransaction()
        {
            if (_companyId >= 0)
                TransactionCollection.GetInstance().RollbackTransaction(System.Threading.Thread.CurrentThread.ManagedThreadId, _companyId);
        }
        #endregion

        #region Status
        public ProcessStatus Status { get; private set; }

        public event EventHandler<ProcessEventArgs<ProcessStatus>> StatusSent;

        public void SendStatus(int progress, string step)
        {
            this.Status.Progress = progress;
            this.Status.Step = step;
            this.SendStatus();
        }

        public void SendStatus(string step)
        {
            this.SendStatus(0, step);
        }

        public void SendStatus()
        {
            if (StatusSent != null)
                StatusSent(this, new ProcessEventArgs<ProcessStatus>(new ProcessStatus(this.Status)));
        }
        #endregion

        public event EventHandler<ProcessEventArgs<Exception>> ProcessThrowAnException;

        protected void HandleException(Exception ex)
        {
            this.HandleException(ex, false);
        }

        protected void HandleException(Exception ex, bool finalize)
        {
            if (ProcessThrowAnException != null)
                ProcessThrowAnException(this, new ProcessEventArgs<Exception>(ex));
            
            if (finalize)
                this.Finalize(true);
        }

        #region Finalize
        public event EventHandler Finalized;
        public event EventHandler Failed;

        public void Finalize()
        {
            this.Finalize(false);
            
        }

        public void Finalize(bool fail)
        {
            if (!fail)
            {
                if (Finalized != null)
                    Finalized(this, new EventArgs());
            }
            else
            {
                if (Failed != null)
                    Failed(this, new EventArgs());
            }
        }
        #endregion

        #region Abort
        public bool IsAborted { get; private set; }

        public event EventHandler Aborted;

        /// <summary>
        /// Interrompe a execução do Processo.
        /// </summary>
        public void Abort()
        {
            this.IsAborted = true;

            if (Aborted != null)
                Aborted(this, new EventArgs());
        }
        #endregion
    }
}
